package com.zy.server.config;

import com.alibaba.fastjson.JSON;
import com.zy.config.RedisKeyConfig;
import com.zy.config.SystemConfig;
import com.zy.third.JedisUtil;
import com.zy.util.StrUtil;
import com.zy.vo.R;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import reactor.core.publisher.Mono;

import java.util.HashSet;
import java.util.Set;

/**
 * @author 张鑫
 * @date 2020/11/29 17:11
 */
@Configuration
public class GatewayFilterConfig {

    //设置认证访问的地址
    // 即需要登录才能进行放行访问
    public Set<String> urls;
    public GatewayFilterConfig() {
        urls = new HashSet<>();
        urls.add("/api/user/checkphone.do");
        urls.add(("/api/smslog/sendcode.do"));
    }

    /**
     * 实现登录验证，检验请求是否需要登录才会放行
     */
    @Bean
    @Order(1)
    public GlobalFilter checkLogin() {
        return ((exchange, chain) -> {
            System.out.println("checkLogin");
            // 获取当前请求
            ServerHttpRequest request = exchange.getRequest();

            // 获取请求的值,即url地址
            String url = request.getPath().value();

            // 校验url是否需要登录
            if (urls.contains(url)) {
                // 需要登录，才能访问
                if (request.getHeaders().containsKey(SystemConfig.TOKEN_EACK)) {
                    // 已经登录，可以访问,放行
                    return chain.filter(exchange);
                } else {
                    // 没有登录，不能放行
                    ServerHttpResponse response = exchange.getResponse();
                    response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
                    return response.writeWith(Mono.just(response.bufferFactory().wrap(JSON.toJSONString(R.fail("亲，请登录后访问哦~")).getBytes())));
                }
            } else {
                return chain.filter(exchange);
            }
        });
    }

    /**
     * 全局过滤器，实现令牌有效性校验
     */
    @Bean
    @Order(2)  // 排名越小越靠前
    public GlobalFilter checkToken() {

        return ((exchange, chain) -> {
            System.out.println("checkToken");
            // 获取请求对象
            ServerHttpRequest request = exchange.getRequest();

            // 校验是否携带令牌
            if (request.getHeaders().containsKey(SystemConfig.TOKEN_EACK)) {
                // 校验令牌
                String token = request.getHeaders().get(SystemConfig.TOKEN_EACK).get(0);
                if (StrUtil.checkNoEmpty(token)) {
                    // 传递令牌
                    if (JedisUtil.getInstance().ishave(RedisKeyConfig.AUTH_TOKEN+token)) {
                        // 令牌存在即有效 可以放行
                        return chain.filter(exchange);
                    }
                }

                // 有令牌，但是无效，没值，进行拦截重新登录
                R r = R.fail("亲，请重新登录之后进行访问哦~");
                // 返回结果
                String jsonString = JSON.toJSONString(r);

                // 获取响应对象
                ServerHttpResponse response = exchange.getResponse();
                // 设置状态响应码
                response.setStatusCode(HttpStatus.NOT_FOUND);
                // 设置响应的数据格式和编码格式
                response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
                // 创建构建的对象
                DataBuffer buffer = response.bufferFactory().wrap(jsonString.getBytes());
                // 拦截请求并返回结果
                return response.writeWith(Mono.just(buffer));
            }
            return chain.filter(exchange);
        });
    }

}
